"""
实例
面向对象开发时
第一步是设计类，将需要的属性和方法封装到类中，在__init__中定义类的属性
使用def(self)定义类的方法

创建出来的对象叫做类的实例
创建对象的动作叫做实例化
对象的属性叫做实例属性
对象调用的方法叫做实例方法

"""

"""
在程序执行时对象拥有自己的实例属性
调用对象方法，可以通过self.
    访问自己的属性
    调用自己的方法

每一个对象都有自己独立的内存空间，保存各自不同的属性
多个对象的方法在内存中只有一份，在调用方法时，需要把对象的引用(self)传递到方法内部


"""


"""
类是一个特殊的对象
class创建的类属于类对象
类实例化的对象属于实例对象

类对象在内存中只有一份
使用一个类可以创建出多个对象实例
除了封装实例的属性和方法外，类对象还可以拥有自己的属性和方法
1.类属性
2.类方法
通过类名.的方式可以访问类的属性或者调用的方法

"""

"""
类属性的定义和使用
类属性就是给类对象中定义的属性
通常用于记录与这个类相关的特征
类属性不会用于记录具体对象的特征

直接使用赋值语句
"""

# class Tool(object):
#     count = 0#记录所有对象的数目
#     def __init__(self,name):
#         self.name = name
#         Tool.count += 1#访问类属性应当使用类名而不是self
#
# print(Tool.count)
# # 未实例化对象，所以__init__未执行，count = 0
# a = Tool("a")
# print(a.count)
# b = Tool("b")
# print(b.count)
# c = Tool("c")
# print(c.count)
# print(a.count)
# print(b.count)
# print(Tool.count)
# # 每一次创建对象，Tool.count在init中都+1，所以每一次输出，值都+1


"""
属性获取机制
向上查找
首先在对象内部查找对象属性，没有找到则向上寻找类属性

类名.类属性
对象.类属性(不推荐使用)

当使用 对象.类属性 = 值 时只会给对象添加一个属性，不会影响到类属性的值

"""
# class Tool(object):
#     count = 0#记录所有对象的数目
#     def __init__(self,name):
#         self.name = name
#         Tool.count += 1#访问类属性应当使用类名而不是self
#
# # 未实例化对象，所以__init__未执行，count = 0
# a = Tool("a")
# b = Tool("b")
# c = Tool("c")
#
# c.count = 99#使用 对象.类属性 = 值
# print(c.count)#只改变对象c中count的值
# print(a.count)#a对象中的count值不改变
# print(Tool.count)#类属性同样不改变
# d = Tool("d")
# print(c.count)
# print(Tool.count)




"""
类方法基本语法

类属性是针对类对象定义的属性
类属性用于记录与这个类相关的特征
在class下方使用赋值语句即可定义类属性

类方法是针对类对象定义的方法
类方法内部可以直接访问类属性或者调用其他类方法

语法:
@classmethod
def 类方法名(cls):
    语句

类方法需要用装饰器@classmethod来标示，告诉解释器这是一个类方法
类方法的第一个参数是cls
    由哪一个类调用的方法，方法内的cls就是哪一个类的引用
    与self类似
    使用其他名称可行，但通常使用cls
通过 类名. 调用类方法，调用类方法时，不需要传递cls参数
在方法内部
    可以通过 cls. 访问类的属性
    也可以通过 cls. 调用其他类方法
"""


# class A(object):
#     a = "a"
#     b = "b"
#     def c(self):
#         print("c")
#     @classmethod
#     def B(cls):
#         print("b")
#     def d(self):
#         A.B()
#     def e(self):
#         A.c()
#
# aaa = A()
# aaa.d()
# aaa.e()#报错


# class Tool(object):
#     count = 0
#     def __init__(self,name):
#         self.name = name
#         Tool.count += 1
#
#     @classmethod
#     def show_count(cls):
#         print(cls.count)
#
#
# a = Tool("a")
# b = Tool("b")
#
# Tool.show_count()



"""
静态方法

在类中封装一个方法
这个方法不需要访问实例属性或调用实例方法
也不需要访问类属性或调用类方法

语法:
@staticmethod
def 静态方法名称():
    语句

静态方法使用@staticmethod标识
通过 类名. 调用静态方法

"""

# class A(object):
#     a = 0
#     @staticmethod
#     def B():
#         #不访问实例属性/类属性
#         print("a")
#     def __init__(self):
#         print("A")
#
# aaa = A()
# A.B()#静态方法使用时不需要创建对象
# aaa.B()


"""
实战
1.设计Game类
2.属性
    定义类属性top_score记录历史最高分
    定义实例属性player_name记录玩家名字
3.方法
静态方法 show_help 显示游戏帮助信息
类犯法 show_top_score 显示历史最高分
实例方法 start_game 开始当前玩家的游戏
4.主程序
查看帮助信息
查看历史最高分
创建游戏对象，开始游戏
"""

# class Game(object):
#     top_score = 0
#     @staticmethod
#     def show_help():
#         print("这里是游戏的帮助信息")
#     @classmethod
#     def show_top_score(cls):
#         print("历史最高分是"+str(cls.top_score))
#     def __init__(self,name):
#         self.name = name
#     def start_game(self):
#         print(self.name+"开始游戏...")
#
# Game.show_help()
# Game.show_top_score()
# p1 = Game("伞兵1号卢本伟")
# p1.start_game()

"""
如何确定方法类型：
如果方法内部需要访问实例属性 ----使用实例方法
    实例方法内部就可以使用 类名. 访问类属性
方法内部“只”需要访问类属性 ----使用类方法
方法内部不需要访问实例属性和类属性 ----静态方法
如果方法内部既需要访问实例属性，又需要访问类属性 ----使用实例方法

类只有一个，在实例方法内部可以使用 类名. 访问类属性

"""










